package com.rem.springboot2;

import ch.qos.logback.classic.db.DBHelper;
import cn.hutool.json.JSONUtil;
import com.rem.springboot2.config.MyConfig;
import com.rem.springboot2.pojo.Person;
import com.rem.springboot2.pojo.Pet;
import com.rem.springboot2.pojo.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;


/**
 * SppringBoot:能快速创建出生产级别的Spring应用
 * 优点：
 * -    创建独立Spring应用
 * -    内嵌web服务器
 * -    自动starter依赖，简化构建配置
 * -    自动配置Spring以及第三方功能
 * -    提供生产级别的监控、健康检查及外部化配置
 * -    无代码生成、无需编写XML
 * 缺点：
 * -    迭代快，需要时刻关注变化
 * -    封装太深，内部原理复杂，不容易精通
 * <p>
 * SpringBoot先加载所有的自动配置类  xxxxxAutoConfiguration
 * -    每个自动配置类按照条件进行生效，默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
 * -    生效的配置类就会给容器中装配很多组件
 * -    只要容器中有这些组件，相当于这些功能就有了定制化配置
 * -         用户直接自己@Bean替换底层的组件
 * -         用户去看这个组件是获取的配置文件什么值就去修改。
 *
 * @author Rem
 * @date 2021/3/17
 */
@SpringBootApplication
public class Springboot2Application {

    public static void main(String[] args) {

        //IOC 容器
        ConfigurableApplicationContext run = SpringApplication.run(Springboot2Application.class, args);

        //从容器中获取组件
        //getContainerBean(run);

        //根据类型获得组件
        //getTypeBean(run);

        //@import 注解测试  注解bean
        //ImportTest(run);

        //测试注解@ImportResource
        //ImportResourceTest(run);


        //@Conditional测试
        //ConditionalTest(run);

        //yml读取配置测试
        // YmlTest(run);

    }

    private static void YmlTest(ConfigurableApplicationContext run) {
        Person bean = run.getBean(Person.class);
        System.out.println(JSONUtil.toJsonStr(bean));
    }

    /**
     * 存在某个条件的时候才创建bean
     *
     * @param run
     */
    private static void ConditionalTest(ConfigurableApplicationContext run) {
        User bean = run.getBean(User.class);
        System.out.println();
    }

    /**
     * 导入配置文件中的内容
     *
     * @param run
     */
    private static void ImportResourceTest(ConfigurableApplicationContext run) {
        //容器里是否包含了这两个实例
        boolean haha = run.containsBean("haha");
        boolean hehe = run.containsBean("hehe");
        //true
        System.out.println(haha);
        //true
        System.out.println(hehe);
    }


    /**
     * 从容器中获取组件
     *
     * @param run
     */
    private static void getTypeBean(ConfigurableApplicationContext run) {
        MyConfig myConfig = run.getBean(MyConfig.class);
        User user = run.getBean(User.class);

        //com.rem.springboot2.config.MyConfig$$EnhancerBySpringCGLIB$$a7581a64@4b1abd11
        System.out.println(myConfig);
        //User(name=zhangsan, age=18, pet=Pet(name=tomcat))
        System.out.println(user);


        Pet tom = run.getBean("tom", Pet.class);
        Pet tom2 = run.getBean("tom", Pet.class);

        // proxyBeanMethods = true 配置为true的时候 创建的就是单实例
        System.out.println("是否创建了单实例:" + (tom == tom2));


        //没有再@bean写名称 默认就是方法的名字
        User user01 = (User) run.getBean("user01");
        System.out.println(user01);

        // proxyBeanMethods = true 配置为true的时候 还是单实例
        System.out.println("验证从属性获得另外一个bean是否是单实例:" + (tom == user01.getPet()));

    }


    /**
     * 查看容器里面的组件
     *
     * @param run
     */
    private static void getContainerBean(ConfigurableApplicationContext run) {
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            /**
             * 除了springbooot默认创建的实例 还有我们自己创建的实例
             * myConfig
             * helloController
             * user01
             * tom
             */
            System.out.println(beanDefinitionName);
        }
    }


    /**
     * @param run
     * @import 注解测试  注解bean
     */
    private static void ImportTest(ConfigurableApplicationContext run) {
        User user = run.getBean(User.class);
        DBHelper dbHelper = run.getBean(DBHelper.class);
        System.out.println(user);
        System.out.println(dbHelper);
    }

}
